
package cn.sj.cordova.rfiduhf;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaWebView;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONException;

import java.util.Iterator;
import java.util.Vector;
import java.util.ArrayList;
import java.util.logging.Logger;

import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;

import com.uhf.linkage.Linkage;
import com.uhf.structures.DynamicQParms;
import com.uhf.structures.FixedQParms;
import com.uhf.structures.Frequency_Region;
import com.uhf.structures.Rfid_Value;
import com.uhf.structures.SelectCriteria;
import com.uhf.structures.Single_Inventory_Time_Config;
import com.uhf.structures.St_Inv_Data;
import com.uhf.structures.TagGroup;
import com.uhf.constants.Constants.InvMode;
import com.uhf.constants.Constants.MemoryBank;
import com.uhf.constants.Constants.RFID_18K6C_COUNTRY_REGION;
import com.uhf.constants.Constants.RFID_18K6C_TAG_MEM_PERM;
import com.uhf.constants.Constants.RFID_18K6C_TAG_PWD_PERM;
import com.uhf.constants.Constants.RFID_INVENTORY_TAG_AREA;
import com.uhf.constants.Constants.Result;



public class RfidUhfPlugin extends CordovaPlugin {

    private static final String TAG = "r2000_native";
    private Linkage lk = new Linkage();
    
    private Handler h = null;
    private int w = 0, r = 0;
    private boolean inSearch = false;
    private Thread invs = null;
    private get_invdata gd;// = new get_invdata();

    public RfidUhfPlugin () {
        OpenDev();
   
    }
    
    public int OpenDev() {
        int fd = lk.Radio_Initialization();
        if(fd == Result.RFID_STATUS_OK.getValue())
        {
            return 0;
        }
        else
        {
            Log.e(TAG, "native open returns null");
            return -1;
        }
    }
    public void CloseDev() {
        lk.DestroyRadioFuncIntegration();
    }
    
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {

        if (action.equals("open")) {
            openRfidUhf(args, callbackContext);
            return true;
        }

        if (action.equals("close")) {
            closeRfidUhf();
            return true;
        }

        return false;
    }

    private void openRfidUhf(final JSONArray args, final CallbackContext callbackContext) throws JSONException {
        
        inventory_start();
        // cordova.getThreadPool().execute(new Runnable() {
        //     public void run() {
                
        //     }
        // });
    }

    private void closeRfidUhf() {
        inventory_stop();
    }
    private class inv_thread extends Thread {
        public void run() {
            super.run();
            int rv = SetAlgorithmDyParameters(lk);
            if(rv != Result.RFID_STATUS_OK.getValue())
            {
                Log.w("r2000", "set alg failed3333333333333333333333333333333333333333333333333333333333333333333333");
            }
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            lk.Inventory(1);
            Log.d("r2000", "inventory thread is stoped************************************************");
        }
    }

    private class get_invdata extends Thread {
            @Override
            public void run() {
                super.run();
                while (inSearch) {
//                  Message msg = new Message();
                    ArrayList<Tag_Data> tg = get_inventory_data();
                    if (tg != null) {
//                      msg.what = 1;
//                      msg.obj = tg;
                        ArrayList<Tag_Data> ks = (ArrayList<Tag_Data>)tg;
                        String tmp[] = new String[ks.size()];
                        for(int i = 0; i < ks.size(); i++)
                        {
                            byte[] nq = ks.get(i).epc;
                            if(nq != null)
                            {
                                tmp[i] = new String();
                                //tmp[i] += "EPC: ";
                                for(int j = 0; j < nq.length; j++)
                                {
                                    tmp[i] += String.format("%02x ", nq[j]);
                                }
                            }
                            
                        }
                        String jsEvent = String.format(
                            "cordova.fireDocumentEvent('rfiduhf.DataReceived',{'rfidUhfData':'%s'})",
                            tmp[0]);
                        webView.sendJavascript(jsEvent);
                        inventory_stop();
//                      h.sendMessage(msg);
                    }
                    try {
                        sleep(100);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        this.interrupt();
                        break;
                    }
                }
                Log.d("r2000", "get data thread is interrupted*************************************");
            }
    }

    public void inventory_start(){
        if(inSearch){
            return;
        }
        inSearch = true;
        invs = new inv_thread();
     
        invs.start();
        gd = new get_invdata();
        gd.start();
    }
    
    public void inventory_stop(){
        if(!inSearch){
            return;
        }
        inSearch = false;
        gd.interrupt();
        invs.interrupt();
        lk.CancelOperation();
    }

    private int SetAlgorithmDyParameters(Linkage link) {
        int status = Result.RFID_STATUS_OK.getValue();
        status = link.Radio_SetCurrentSingulationAlgorithm(1);
        if (status != Result.RFID_STATUS_OK.getValue())
            return status;
        TagGroup group = new TagGroup();
        status = link.Radio_GetQueryTagGroup(group);
        if (status != Result.RFID_STATUS_OK.getValue())
            return status;
        group.session = 2;
        status = link.Radio_SetQueryTagGroup(group);
        if (status != Result.RFID_STATUS_OK.getValue())
            return status;
        DynamicQParms dynamic = new DynamicQParms();
        dynamic.minQValue = 0;
        dynamic.maxQValue = 15;
        dynamic.retryCount = 0;
        dynamic.startQValue = 4;
        dynamic.thresholdMultiplier = 4;
        dynamic.toggleTarget = 1;
        status = link.Radio_SetSingulationAlgorithmDyParameters(dynamic);
        if (status != Result.RFID_STATUS_OK.getValue())
            return status;
        return status;
    }

    public class Tag_Data {
        Tag_Data(byte[] n_tid, byte[] n_epc) {
            tid = n_tid;
            epc = n_epc;
        }

        public byte[] tid;
        public byte[] epc;
    }

    private ArrayList<Tag_Data> get_inventory_data()
    {
        ArrayList<Tag_Data> cx = new ArrayList<Tag_Data>();
        St_Inv_Data[] arg0 = new St_Inv_Data[512];
        int sn = lk.GetInvData(arg0);
        Log.e("sasa", "get " + sn + " cards");
        if((sn > 0) && (arg0 != null))
        {
            for(int i = 0; i < sn; i++)
            {
                Log.e("asas", "epc leng is " + arg0[i].nLength + " tid leng is " + arg0[i].tidLength);
                if((arg0[i].nLength > 0) && (arg0[i].nLength < 66))
                {
                    byte[] n_epc = new byte[arg0[i].nLength];
                    byte[] n_tid;
                    System.arraycopy(arg0[i].INV_Data, 0, n_epc, 0, n_epc.length);
                    if(arg0[i].tidLength == 12)
                    {
                        n_tid = new byte[arg0[i].tidLength];
                        System.arraycopy(arg0[i].TID_Data, 0, n_tid, 0, n_tid.length);
                    }
                    else
                    {
                        n_tid = null;
                    }
                    cx.add(new Tag_Data(n_tid, n_epc));
                }
            }
            return cx;
        }
        return null;
    }

    // public void onDataReceived(final String port, final String input) {
    //     try {
    //         cordova.getActivity().runOnUiThread(new Runnable() {
    //             public void run() {
    //                 String jsEvent = String.format(
    //                         "cordova.fireDocumentEvent('serialport.DataReceived',{'serialPort':'%s','serialPortData':'%s'})",
    //                         port, input);
    //                 webView.sendJavascript(jsEvent);
    //             }
    //         });
    //     } catch (Exception e) {
    //         e.printStackTrace();
    //     }
    // }

    @Override
    public void onDestroy() {
        super.onDestroy();
        inventory_stop();
        CloseDev();
        
    }
}